const app = getApp()

export default {
    /**
     * 初始化蓝牙设备
     * */
    initBlueTooth () {
        return new Promise((resolve, reject) => {
            wx.closeBluetoothAdapter()
            // 初始化蓝牙模块
            wx.openBluetoothAdapter({
                success: res => {
                    console.log('初始化蓝牙模块成功', res)
                    resolve()
                },
                fail (err) {
                    console.log('初始化蓝牙模块失败', err)
                    reject()
                }
            })
        })
    },
    /**
     * 初始化蓝牙设备并监听设备状态变化
     */
    startConnect () {
        return new Promise((resolve, reject) => {
            /* 获取蓝牙适配器状态
             * discovering  是否正在搜索设备
             * available  蓝牙适配器是否可用
             * */
            this.getBluetoothAdapterState()
                .then(() => {
                    // const {available} = res
                    // if (available) {
                    //     console.log('蓝牙适配器可用，无需初始化')
                    //     resolve()
                    // } else {
                    console.log('蓝牙适配器不可用，初始化')
                    this.initBlueTooth()
                        .then(() => {
                            resolve()
                        })
                        .catch(e => {
                            reject(e)
                        })
                    // }
                })
                .catch(e => {
                    console.log('蓝牙适配器不可用，初始化', e)
                    this.initBlueTooth()
                        .then(() => {
                            resolve()
                        })
                        .catch(e => {
                            reject(e)
                        })
                })
        })
    },
    /**
     * 获取本机蓝牙适配器状态
     * https://developers.weixin.qq.com/miniprogram/dev/api/wx.getBluetoothAdapterState.html
     */
    getBluetoothAdapterState () {
        return new Promise((resolve, reject) => {
            wx.getBluetoothAdapterState({
                success: res => {
                    console.log('获取本机蓝牙适配器状态成功', res)
                    resolve(res)
                },
                fail: e => {
                    console.log('获取本机蓝牙适配器状态失败', e)
                    reject(e)
                }
            })
        })
    },
		/**
     * 监听寻找到新设备的事件
     * */
    onBluetoothDeviceFound (services = []) {
			return new Promise((resolve, reject) => {
						wx.getBluetoothDevices({
							success: (res) => {
									var blueToothList = []
									console.log(res.devices,'搜素到的设备')
									for (var i = 0; i < res.devices.length; i++) {
											if (res.devices[i].name != "未知设备") {
													blueToothList.push(res.devices[i])
											}
									}
									resolve(blueToothList)
							},
							fail: function () {
									console.log("搜索蓝牙设备失败")
							}
					})
			})
		},
    /**
     * 搜索蓝牙设备
     * */
    startSearchBlueTooth (services = []) {
        return new Promise((resolve, reject) => {
            wx.startBluetoothDevicesDiscovery({
                services,
                allowDuplicatesKey: true,
                success: res => {
                    console.log('启动搜索蓝牙设备', res)
                    resolve(res)
                },
                fail: err => {
                    console.log('搜索蓝牙设备失败', err)
                    reject(err)
                }
            })
        })
    },
    /**
     * 停止搜索蓝牙设备
     * */
    stopSearchBlueTooth () {
        return new Promise((resolve, reject) => {
            wx.stopBluetoothDevicesDiscovery({
                success: res => {
                    console.log('停止搜索蓝牙设备', res)
                    resolve(res)
                },
                fail: err => {
                    console.log('停止搜索蓝牙设备失败', err)
                    reject(err)
                }
            })
        })
    },
    /**
     * 获取处于已连接状态的设备
     */
    getConnectedBluetoothDevices () {
        return new Promise((resolve, reject) => {
            wx.getConnectedBluetoothDevices({
                services: [],
                success: res => {
                    console.log('获取处于已连接状态的设备', res)
                    resolve(res.devices)
                },
                fail: e => {
                    console.log('获取处于已连接状态的设备失败', e)
                    reject(e)
                }
            })
        })
    },

    /**
     * 获取蓝牙设备所有服务，获取特征值中用到 已废弃
     * @param deviceId {String}  设备id
     * @param options {Object}  配置信息
     * @param options.isWrite {Boolean}  是否过滤可读属性
     * */
    getBLEDeviceServices (deviceId, options = {}) {
        let { isWrite = true, readDir = true } = options

        return new Promise((resolve, reject) => {
            // 获取蓝牙设备所有服务
            wx.getBLEDeviceServices({
                deviceId,
                success: res => {
                    console.log('获取蓝牙设备所有 service 成功', res)
                    const services = res.services

                    if (readDir) {
                        const nextFn = macDir => {
                            const len = services.length
                            let num = 0
                            let characteristics = []
                            const rejFn = () => {
                                num += 1
                                if (num === len) {
                                    if (characteristics.length > 0) {
                                        const len = characteristics.length
                                        console.log(
                                            `获取到${len}条符合条件的特征值数据`,
                                            characteristics
                                        )
                                        const list = characteristics.map(
                                            item => {
                                                item.macDir = macDir
                                                return item
                                            }
                                        )
                                        resolve(list)
                                    } else {
                                        reject({
                                            message: '没有符合条件的特征值数据',
                                            macDir
                                        })
                                    }
                                }
                            }
                            for (let item of services) {
                                this.getCharacteristic(
                                    deviceId,
                                    item.uuid,
                                    isWrite
                                )
                                    .then(res => {
                                        console.log('获取特征值成功', res)
                                        characteristics.push(...res)
                                        rejFn()
                                    })
                                    .catch(() => {
                                        rejFn()
                                    })
                            }
                        }
                        // 获取mac地址
                        this.getMacDir({ deviceId, services }).then(res => {
                            console.log('MAC地址', res)
                            nextFn(res)
                        })
                    } else {
                        resolve(services)
                    }
                },
                fail: e => {
                    console.log('获取蓝牙设备所有 service失败', e)
                    reject(e)
                }
            })
        })
    },
    /**
     * 获取特征值characteristic 已废弃
     * @param deviceId {String} 设备id
     * @param serviceId {String} 服务id 服务列表中的uuid
     * @param isWrite {Boolean} 是否过滤可写属性 @default true
     * */
    getCharacteristic (deviceId, serviceId, isWrite = true) {
        return new Promise((resolve, reject) => {
            wx.getBLEDeviceCharacteristics({
                deviceId,
                serviceId,
                success: res => {
                    let characteristics = res.characteristics.filter(item => {
                        const { read, write, notify } = item.properties
                        if (isWrite) {
                            return read && write && notify
                        } else {
                            return read && notify
                        }
                    })
                    characteristics = characteristics.map(item => {
                        item.serviceId = serviceId
                        return item
                    })
                    console.log('获取特征值characteristic成功', characteristics)
                    if (characteristics.length > 0) {
                        resolve(characteristics)
                    } else {
                        console.log('未获取到可读写的特征值')
                        reject({
                            errMsg: '未获取到可读写的特征值'
                        })
                    }
                },
                fail: e => {
                    console.log('获取特征值characteristic失败', e)
                    reject({
                        errMsg: '获取特征值失败'
                    })
                }
            })
        })
    },
    /**
     * 连接后获取设备 MAC 地址
     * @param {Array} deviceId 设备ID
     * @param {Array} serviceId 服务ID
     * @param {String} characteristicId 特征值ID
     * */
    getMacDir (deviceId, serviceId, characteristicId) {
        return new Promise((resolve, reject) => {
            wx.readBLECharacteristicValue({
                deviceId,
                serviceId,
                characteristicId,
                success: res => {
                    console.log(
                        '读取低功耗蓝牙设备的特征值的二进制数据值成功',
                        res
                    )
                },
                fail: e => {
                    const eObj = {
                        message: '读取低功耗蓝牙设备的特征值的二进制数据值失败',
                        detail: e
                    }
                    console.error(eObj)
                    console.log(deviceId, serviceId, characteristicId)
                    reject(eObj)
                }
            })
        })
    },
    newGietMacDir (deviceId, serviceId, characteristicId) {
        return new Promise((resolve, reject) => {
            // 获取服务列表
            this.initService2characteristic(deviceId, serviceId).then(() => {
                wx.onBLECharacteristicValueChange(res => {
                    // console.log('二进制数据值：', res)
                    const mac = this.macBuf2String(res.value)
                        .join('')
                        .toLocaleUpperCase()
                    // console.log('MAC地址', mac)
                    resolve(mac)
                })
                console.log('连接后获取设备MAC地址')
                console.log(serviceId, characteristicId)
                wx.readBLECharacteristicValue({
                    deviceId,
                    serviceId,
                    characteristicId,
                    success: res => {
                        console.log(
                            '读取低功耗蓝牙设备的特征值的二进制数据值成功',
                            res
                        )
                    },
                    fail: e => {
                        const eObj = {
                            message:
                                '读取低功耗蓝牙设备的特征值的二进制数据值失败',
                            detail: e
                        }
                        console.error(eObj)
                        reject(eObj)
                    }
                })
            })
        })
    },
    /**
     * 获取服务列表和特征值已完成后续动作
     * */
    initService2cs (deviceId, serviceId) {
        return new Promise((resolve, reject) => {
            // 获取服务列表
            wx.getBLEDeviceServices({
                deviceId,
                success: s => {
                    wx.getBLEDeviceCharacteristics({
                        deviceId,
                        serviceId,
                        success: c => {
                            resolve({ s, c })
                        },
                        fail: e => {
                            reject(e)
                        }
                    })
                },
                fail: e => {
                    reject(e)
                }
            })
        })
    },
    /**
     * 关闭/开启notify 默认开启
     * @param state {Boolean}  @default true -开启/关闭Notify
     * @param options {Object}  @default {}
     * */
    toggleNotify (state = true, options = {}) {
        const { deviceId, serviceId, characteristicId } = options
        return new Promise((resolve, reject) => {
            wx.notifyBLECharacteristicValueChange({
                state,
                deviceId,
                serviceId,
                characteristicId,
                success: res => {
                    resolve(res)
                },
                fail: e => {
                    reject(e)
                }
            })
        })
    },

    /**
     * 获取绑定的默认设备，用于自动连接
     * */
    async getDefaultDevice () {
        try {
            console.log('获取默认设备')
            const res = await this.getHistoryDevIces()
            console.log(res)
            if (!res) {
                return Promise.reject({
                    code: 'list_none',
                    message: '您还没有添加设备'
                })
            }
            let list = []
            for (let [, value] of Object.entries(res)) {
                list.push(value)
            }
            if (list.length === 0) {
                return null
            } else if (list.length === 1) {
                return list[0]
            } else {
                let arr = list.filter(item => {
                    return item.defaultDevice === true
                })
                if (arr.length > 0) {
                    return arr[0]
                } else {
                    // 存在多个且没有默认设备
                    return Promise.reject({
                        code: 'default_none',
                        message:
                            '您还没有绑定默认设备哦，请在 我的 > 我的设备 页面中进行设备绑定，绑定完成后再次点击上秤即可开始进行检测'
                    })
                }
            }
        } catch (e) {
            return Promise.reject(e)
        }
    },

    /**
     * 指令发送到蓝牙
     * @param value {String} 要发送字符串
     */
    sendDataToBLE (value) {
        const connectionItem = app.globalData.balanceData.connectionItem
        const { deviceId, serviceId, characteristicId } = connectionItem
        return new Promise((resolve, reject) => {
            if (!connectionItem) {
                reject({
                    message: '未连接设备'
                })
                return
            } else {
                if (!deviceId || !serviceId || !characteristicId) {
                    reject({
                        message: '缺少必要参数',
                        detail: { deviceId, serviceId, characteristicId }
                    })
                    return
                }
            }
            console.log('发送的数据------------------------------')
            console.log(value)
            const buffer = this.string2buf(value)
            console.log('发送的Buffer数据-----------------------------')
            console.log(buffer)
            wx.writeBLECharacteristicValue({
                deviceId: deviceId,
                serviceId: serviceId,
                characteristicId: characteristicId,
                value: buffer,
                success: res => {
                    console.log('发送成功', res)
                    resolve(res)
                },
                fail: e => {
                    console.error('发送失败', e)
                    reject(e)
                }
            })
        })
    },
    sendDataToBLECb (value, cb) {
        console.log(value)
        console.log('------------sss222')
        // 先取消监听
        wx.offBLECharacteristicValueChange()
        wx.onBLECharacteristicValueChange(res => {
            const resValue = this.buf2string(res.value)
            if (typeof cb === 'function') {
                cb({
                    value: resValue,
                    originValue: res.value
                })
            }
        })
        if (value === false) {
            return
        }
        return this.sendDataToBLE(value)
    },
    /**
     * ArrayBuffer转16进制字符串
     * */
    ab2hex (buffer) {
        return this.ab2hexArr(buffer).join('')
    },
    /**
     * ArrayBuffer转16进制字符串数组
     * */
    ab2hexArr (buffer) {
        return Array.prototype.map.call(new Uint8Array(buffer), function (bit) {
            return ('00' + bit.toString(16)).slice(-2)
        })
    },
    /**
     * 字符串转16进制ArrayBuffer
     * */
    string2buf (str) {
        // 首先将字符串转为16进制
        let val = ''
        for (let i = 0; i < str.length; i++) {
            if (val === '') {
                val = str.charCodeAt(i).toString(16)
            } else {
                val += ',' + str.charCodeAt(i).toString(16)
            }
        }
        // 将16进制转化为ArrayBuffer
        return new Uint8Array(
            val.match(/[\da-f]{2}/gi).map(function (h) {
                return parseInt(h, 16)
            })
        ).buffer
    },
    /**
     *
     * */
    macBuf2String (buffer) {
        let hexArr = this.ab2hex(buffer)
        return [
            hexArr[7],
            hexArr[6],
            hexArr[5],
            hexArr[2],
            hexArr[1],
            hexArr[0]
        ]
    },
    /**
     * ArrayBuffer转字符串
     * */
    buf2string (buffer) {
        let arr = Array.prototype.map.call(new Uint8Array(buffer), x => x)
        return arr
            .map(char => {
                return String.fromCharCode(char)
            })
            .join('')
    },
    // 日期效验
    isDate (str) {
        if (!str) return false
        const r = str.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/)
        if (!r) return false
        const d = new Date(r[1], Number(r[3]) - 1, r[4])
        return (
            d.getFullYear() == r[1] &&
            d.getMonth() + 1 == r[3] &&
            d.getDate() == r[4]
        )
    },
    // 根据出生日期获取周岁年龄
    getAge (strBirthday) {
        let returnAge
        let strBirthdayArr = strBirthday.split('-')
        let birthYear = strBirthdayArr[0]
        let birthMonth = strBirthdayArr[1]
        let birthDay = strBirthdayArr[2]
        let d = new Date()
        let nowYear = d.getFullYear()
        let nowMonth = d.getMonth() + 1
        let nowDay = d.getDate()
        if (nowYear == birthYear) {
            returnAge = 0 //同年则为0岁
        } else {
            let ageDiff = nowYear - birthYear //年之差
            if (ageDiff > 0) {
                if (nowMonth == birthMonth) {
                    let dayDiff = nowDay - birthDay //日之差
                    if (dayDiff < 0) {
                        returnAge = ageDiff - 1
                    } else {
                        returnAge = ageDiff
                    }
                } else {
                    let monthDiff = nowMonth - birthMonth //月之差
                    if (monthDiff < 0) {
                        returnAge = ageDiff - 1
                    } else {
                        returnAge = ageDiff
                    }
                }
            } else {
                returnAge = -1 //返回-1 表示出生日期输入错误 晚于今天
            }
        }
        return returnAge // 返回周岁年龄
    }
}
